package com.chengh.nami.core.security.service;

import com.chengh.nami.core.async.AsyncManager;
import com.chengh.nami.core.async.factory.AsyncFactory;
import com.chengh.nami.core.security.contextHolder.AuthenticationContextHolder;
import com.chengh.nami.common.constants.CacheConstants;
import com.chengh.nami.common.constants.Constants;
import com.chengh.nami.common.domain.model.LoginBody;
import com.chengh.nami.common.domain.model.LoginUserEntity;
import com.chengh.nami.common.exception.BizException;
import com.chengh.nami.common.utils.StringUtils;
import com.chengh.nami.common.utils.redis.RedisCache;
import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

/**
 * 登录校验方法
 *
 * @author chengh
 */
@Component
@RequiredArgsConstructor
public class LoginService {

    private final AuthenticationManager authenticationManager;

    private final TokenService tokenService;

    private final RedisCache redisCache;

    public String login(LoginBody loginBody) {
        // 校验验证码
        validateCaptcha(loginBody);
        Authentication authentication;
        try {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginBody.getUsername(), loginBody.getPassword());
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);
        } catch (Exception e) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_FAIL, e.getMessage()));
            throw e;
        } finally {
            AuthenticationContextHolder.clearContext();
        }
        AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_SUCCESS, "登录成功"));
        LoginUserEntity loginUserEntity = (LoginUserEntity) authentication.getPrincipal();
        return tokenService.createToken(loginUserEntity);
    }

    /**
     * 校验验证码
     *
     * @param loginBody 登陆信息
     */
    private void validateCaptcha(LoginBody loginBody) {
        if (StringUtils.isEmpty(loginBody.getUuid())) {
            throw new BizException("验证码不能为空");
        }
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + loginBody.getUuid();
        String captcha = redisCache.getCacheObject(verifyKey);
        redisCache.deleteObject(verifyKey);
        if (captcha == null) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_FAIL, "验证码过期"));
            throw new BizException("验证码过期,请重新获取验证码!");
        }
        if (!captcha.equals(loginBody.getCode())) {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(loginBody.getUsername(), Constants.LOGIN_FAIL, "验证码错误"));
            throw new BizException("验证码不正确");
        }
    }
}
